import time
import bcrypt
from ..main import app, db, logger
from ..models import User, Booking, UserWithoutPassword, NewUserData
from ..exceptions import UserNotFound
from typing import Union
import json
from fastapi import HTTPException
import uuid

path = '/api/users'


@app.get(path + "/get_users", tags=['users'])
async def get_users_api():
    try:
        users = await db.get_users()
    except Exception:
        logger.error("Error while execute get_users db_method", exc_info=True)
        raise HTTPException(status_code=500, detail="Internal error.")
    return users


@app.get(path + "/get_user/{user_id}", tags=['users'])
async def get_user_api(user_id: str):
    try:
        user_id = uuid.UUID(user_id)
        user = await db.get_user(user_id)
    except ValueError:
        raise HTTPException(status_code=400, detail="user_id must be uuid string")
    except UserNotFound:
        raise HTTPException(status_code=404, detail="user with that id not found")
    except Exception as ex:
        logger.error(f"Error while execute get_user db_method (uid: {user_id}, errmsg: {ex})", exc_info=True)
        raise HTTPException(status_code=500, detail="unexpected error")
    return user


@app.post(path + '/add_user', tags=['users'])
async def add_user_api(new_user_data: NewUserData):
    data = {
        "user_id": uuid.uuid4(),
        "username": new_user_data.username,
        "created_at": time.time() if new_user_data.created_at is None else new_user_data.created_at,
    }
    full_data = data.copy()
    password = new_user_data.password.encode()
    full_data['password'] = bcrypt.hashpw(password, bcrypt.gensalt())
    user = User(**full_data)
    await db.add_user(user)
    return UserWithoutPassword(**data)


@app.get(path + '/del_user/{user_id}', tags=['users'])
async def get_user_api(user_id: str):
    try:
        user_id = uuid.UUID(user_id)
        user = await db.get_user(user_id)
        await db.del_user(user_id)
    except ValueError:
        raise HTTPException(status_code=400, detail="user_id must be uuid string")
    except UserNotFound:
        raise HTTPException(status_code=404, detail="user with that id not found")
    except Exception as ex:
        logger.error(f"Error while execute del_user db_method (uid: {user_id}, errmsg: {ex})", exc_info=True)
        raise HTTPException(status_code=500, detail="unexpected error")
    return "success"
